package net.cloudcodex.client;

import net.cloudcodex.client.sheet.IsSheet;
import net.cloudcodex.client.sheet.Sheet;

import com.allen_sauer.gwt.dnd.client.DragContext;
import com.allen_sauer.gwt.dnd.client.VetoDragException;
import com.allen_sauer.gwt.dnd.client.drop.DropController;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.LayoutPanel;
import com.google.gwt.user.client.ui.Widget;

/**
 * 
 * 
 * @author ADaroussin
 */
public class MainView extends LayoutPanel implements DropController {

	private static final int TITLE_HEIGHT = 90;
	private static final int FOOTER_HEIGHT = 100;

	private final MainArea mainArea;
	private final MainFooter mainFooter;

	private final ClickHandler previewClickHandler = new ClickHandler() {
		public void onClick(ClickEvent event) {
			final IsSheet sheet = (IsSheet) event.getSource();
			currentSheet = setSheet(sheet.asSheet());
		}
	};

	private Sheet currentSheet;

	public MainView() {
		this.setStylePrimaryName("ccMainView");
		final MainTitle mainTitle = new MainTitle();
		this.add(mainTitle);
		this.setWidgetTopHeight(mainTitle, 0, Unit.PX, TITLE_HEIGHT, Unit.PX);
		mainArea = new MainArea();
		this.add(mainArea);
		this.setWidgetTopBottom(mainArea, TITLE_HEIGHT, Unit.PX, FOOTER_HEIGHT, Unit.PX);
		mainFooter = new MainFooter();
		this.add(mainFooter);
		this.setWidgetBottomHeight(mainFooter, 0, Unit.PX, FOOTER_HEIGHT, Unit.PX);
	}

	public Widget getDropTarget() {
		return this;
	}

	public void onDrop(DragContext context) {
		final Sheet newSheet = ((IsSheet) context.draggable).asSheet();
		final AbsolutePanel boundaryPanel = context.dragController.getBoundaryPanel();

		int left = this.getAbsoluteLeft();
		int top = this.getAbsoluteTop() + TITLE_HEIGHT;

		if (currentSheet != null) {
			boundaryPanel.add(currentSheet.title(), left, top);
			boundaryPanel.setWidgetPosition(currentSheet.title().asWidget(), currentSheet.leftPosition(),
					currentSheet.topPosition());
			// sheets linked to current sheet are moved back their positions
			for (Sheet sheet : currentSheet.links()) {
				final Widget preview = sheet.preview().asWidget();
				final Widget title = sheet.title().asWidget();
				preview.removeStyleDependentName("linked");
				title.removeStyleDependentName("linked");
				boundaryPanel.setWidgetPosition(preview, sheet.leftPosition(), sheet.topPosition());
				if (sheet == currentSheet) {
					boundaryPanel.add(currentSheet.title(), left, top);
				}
				boundaryPanel.setWidgetPosition(title, sheet.leftPosition(), sheet.topPosition());
				sheet.preview().removeClickHandler(previewClickHandler);
			}
		}

		// sheets linked to new sheet are moved next
		for (Sheet sheet : newSheet.links()) {
			if (sheet != currentSheet &&  sheet != newSheet) {
				sheet.savePosition();
			}
			final Widget preview = sheet.preview().asWidget();
			final Widget title = sheet.title().asWidget();
			boundaryPanel.add(preview, title.getAbsoluteLeft(), title.getAbsoluteTop());
			preview.addStyleDependentName("linked");
			title.addStyleDependentName("linked");
			boundaryPanel.setWidgetPosition(preview, left - preview.getOffsetWidth(), top);
			if (sheet == newSheet) {
				boundaryPanel.add(title, left, top);
			}
			boundaryPanel.setWidgetPosition(title, left - preview.getOffsetWidth(), top);
			sheet.preview().addClickHandler(previewClickHandler);
			top += preview.getOffsetHeight();
		}

		currentSheet = null;
	}

	public void onEnter(DragContext context) {
		this.addStyleDependentName("engage");

		final Sheet sheet = ((IsSheet) context.draggable).asSheet();

		currentSheet = setSheet(sheet);
	}

	public void onLeave(DragContext context) {
		this.removeStyleDependentName("engage");
		if (context.finalDropController == null) {
			// Sheet was finally not dropped
			setSheet(currentSheet);
			currentSheet = null;
		}
	}

	public void onMove(DragContext context) {
		// Do nothing
	}

	public void onPreviewDrop(DragContext context) throws VetoDragException {
		// Do nothing
	}

	protected Sheet setSheet(Sheet sheet) {
		final Sheet oldSheet = (Sheet) mainArea.getWidget();

		// Set the sheet content
		mainArea.setWidget(sheet);

		final IsSheet footer = (sheet == null ? null : sheet.footer());
		// Set the sheet footer
		mainFooter.setWidget(footer);

		final int height = (sheet == null ? FOOTER_HEIGHT : footer.asWidget().getOffsetHeight());
		// Change footer heigh
		this.setWidgetTopBottom(mainArea, TITLE_HEIGHT, Unit.PX, height, Unit.PX);
		this.setWidgetBottomHeight(mainFooter, 0, Unit.PX, height, Unit.PX);

		return oldSheet;
	}

}
